package operations;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.LinkedList;


public class CreateList extends Operation{
	  // State variables.
	private final String ref;
	  private  int length;
	  private final Class<?> elementType;
	  private final List<Object> inputVariables;
	  
	  private List<Class<?>> inputTypesCached;
	  private Class<?> outputTypeCached;    

	  public CreateList(String ref,Class<?> elementType, int length,List<Object> inputVariables) {

		    // Check legality of arguments.
		    if (elementType == null) throw new IllegalArgumentException("elementType cannot be null.");
		    if (length < 0) throw new IllegalArgumentException("arity cannot be less than zero: " + length);

		    // Set state variables.
		    this.ref=ref;
		    this.elementType = elementType;
		    this.length = length;
		    this.inputVariables= new LinkedList<Object>(inputVariables);
		  }
	  public Class<?> getElementType() {
		    return this.elementType;
		  }
	  public String getReference() {
		    return this.ref;
		  }
	  public List<Object> getInputVariables() {
		    return this.inputVariables;
		  }
	  public int getLength() {
		    return this.length;
		  }
	  public void setLength(int Length){
		  if(Length>=0)
			  this.length=Length;
	  }
		  /**
		   * Extracts the input constraints for this ArrayDeclarationInfo
		   * @return list of input constraints
		   */
		  public List<Class<?>> getInputTypes() {
		    if (inputTypesCached == null) {
		      this.inputTypesCached = new ArrayList<Class<?>>(length);
		      for (int i = 0 ; i < length ; i++)
		        inputTypesCached.add(elementType);
		      inputTypesCached = Collections.unmodifiableList(inputTypesCached);
		    }
		    return Collections.unmodifiableList(this.inputTypesCached);
		  }
		  @Override
		  public String toString() {
			    return   ref + "= new " +elementType.getName() + "[" + Integer.toString(length) + "]";

//		    return "array_of_" + this.elementType.getSimpleName() + "_of_size_" + this.length;
		  }

		  public Class<?> getOutputType() {
			    if (outputTypeCached == null) {
			      outputTypeCached = Array.newInstance(elementType, 0).getClass();
			    }
			    return outputTypeCached;
			  }
		  public String toParseableString(Map<String,Class<?>> classesToTest) {
			    return  elementType.getName()+"[]" + ref + "=" +elementType.getName() + "[" + Integer.toString(length) + "]";
			  }

		  @Override
			public Operation clone() {
				List<Object> cloneInputVariables=new ArrayList<Object>(inputVariables);
				final CreateList clone =new CreateList(ref,elementType,  length, cloneInputVariables);
				return clone;
			}

}
